package fina2.dcs.fis;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import javax.ejb.EJB;
import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;

import org.jboss.annotation.ejb.LocalBinding;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.Synchronized;
import org.jboss.seam.log.Log;

import fina2.dcs.i18n.LanguageSession;
import fina2.dcs.system.SysString;
import fina2.dcs.system.SysStringLocal;
import fina2.dcs.system.SysStringPk;
import fina2.dcs.system.SysUserBank;

@Stateful
@Name("bankSession")
@Scope(ScopeType.SESSION)
@LocalBinding(jndiBinding = "BankSession/local")
@SuppressWarnings("unchecked")
@Synchronized(timeout = 5000)
@AutoCreate
public class BankSession implements BankLocal, Serializable {

	@PersistenceContext
	private EntityManager em;

	private ArrayList<String> codes = new ArrayList<String>();
	private List<Bank> allBanks = null;
	
	@Logger
	private Log log;

	@EJB
	private SysStringLocal sysStringLocal;
	@EJB
	private BankTypeLocal btLocal;

	public void init() {

	}

	public Bank findById(BigDecimal id) {
		Bank b = null;
		b = em.find(Bank.class, id);
		return b;
	}

	public List<String> findCodesByIds(String ids) {
		List<String> banks = new ArrayList<String>();
		try {
			banks = em.createQuery("SELECT b.code FROM " + Bank.class.getName() + " b WHERE b.id IN(" + ids + ") ORDER BY b.code ASC").getResultList();
		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
		}
		return banks;
	}

	public long getBanksCount(BigDecimal userId) {
		long count = 0;
		count = (Long) em.createQuery("SELECT count(b.code) as banks_size FROM " + Bank.class.getName() + " b WHERE b.id IN(" + " SELECT sub.userBankPk.bankId FROM " + SysUserBank.class.getName() + " sub WHERE sub.userBankPk.userId=" + userId + ")").getSingleResult();
		return count;
	}

	public List<Bank> findByIds(String ids) {
		List<Bank> banks = new ArrayList<Bank>();
		try {
			banks = em.createQuery("FROM " + Bank.class.getName() + " b WHERE b.id IN(" + ids + ") ORDER BY b.code ASC").getResultList();
		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
		}
		return banks;
	}

	public List<Bank> getAllBanks() {
		init();
		List<Bank> list = em.createQuery("FROM " + Bank.class.getName() + " b ORDER BY b.code").getResultList();
		List<BigDecimal> ids = new ArrayList<BigDecimal>();
		for (int i = 0; i < list.size(); i++) {
			ids.add(list.get(i).getNamestrid());
		}

		StringBuffer sb = new StringBuffer(ids.toString());

		sb.replace(0, 1, "");
		sb.replace(sb.length() - 1, sb.length(), "");
		List<SysString> names = sysStringLocal.getAllValues(sb.toString(), LanguageSession.langId);
		for (int i = 0; i < list.size(); i++)
			for (int j = 0; j < names.size(); j++) {
				if (list.get(i).getNamestrid().equals(names.get(j).getPk().getId())) {
					list.get(i).setName(names.get(j).getValue());
					break;
				}
			}

		for (int i = 0; i < list.size(); i++) {
			list.get(i).setBankType(getBankTypeByTypeId(list.get(i).getTypeId()));
		}
		return list;
	}

	public List<String> getAllBankCodes() {
		List<String> bankCodes = null;
		try {
			bankCodes = em.createQuery("SELECT rtrim(b.code) FROM " + Bank.class.getName() + " b ORDER BY b.code").getResultList();
		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
		}
		return bankCodes;
	}

	@Remove
	@Destroy
	public void remove() {

	}

	public List<Bank> getBanksByTypeId(String typeId) {
		List<Bank> bList = null;
		try {
			bList = (List<Bank>) em.createQuery("FROM " + Bank.class.getName() + " b WHERE RTRIM(b.typeId) IN(" + typeId + ") ORDER BY b.code").getResultList();
			if (bList != null)
				for (int i = 0; i < bList.size(); i++) {
					SysStringPk pk = new SysStringPk(bList.get(i).getNamestrid(), LanguageSession.langId);
					bList.get(i).setName(sysStringLocal.findByPk(pk).getValue());
				}
		} catch (Exception ex) {
			log.error(ex);
		}
		return bList;
	}

	public BankType getBankTypeByTypeId(BigDecimal typeId) {
		init();
		return btLocal.findById(typeId);
	}

	@Override
	public List<Bank> getBanksByPrefix(Object p) {
		try {

			String sql = "FROM " + Bank.class.getName() + " b ORDER BY b.code";
			allBanks = em.createQuery(sql).getResultList();
			for (int i = 0; i < allBanks.size(); i++) {
				SysStringPk pk = new SysStringPk(allBanks.get(i).getNamestrid(), LanguageSession.langId);
				SysString ss = sysStringLocal.findByPk(pk);
				if (ss != null)
					allBanks.get(i).setName(ss.getValue());

			}
			for (int i = 0; i < allBanks.size(); i++) {
				if ((!allBanks.get(i).getCode().toString().toLowerCase().trim().contains(p.toString().toLowerCase().trim())) && (!allBanks.get(i).getName().toLowerCase().trim().contains(p.toString().toLowerCase().trim()))) {
					allBanks.remove(i);
					i--;
				}
			}
		} catch (Exception ex) {
			log.error(ex);
		}
		return allBanks;
	}

	public Bank findByCode(String code) {
		Bank b = null;
		try {
			b = (Bank) em.createQuery("FROM " + Bank.class.getName() + " b WHERE RTRIM(b.code)=:code").setParameter("code", code.trim()).getSingleResult();
		} catch (NoResultException ex) {
			log.info("Bank with code " + code + " does not exist");
		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
		}
		return b;
	}

	public void addBank(Bank b) {
		try {
			em.persist(b);
		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
		}
	}

	public BigDecimal getMaxId() {
		BigDecimal maxId = new BigDecimal("0");
		try {
			maxId = (BigDecimal) em.createQuery("SELECT MAX(id) FROM " + Bank.class.getName() + " b").getSingleResult();
			if (maxId == null)
				maxId = new BigDecimal("1");
		} catch (NoResultException ex) {
			maxId = new BigDecimal("1");
		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
		}
		return maxId;
	}

	public ArrayList<String> getCodes() {
		return codes;
	}

	public void setCodes(ArrayList<String> codes) {
		this.codes = codes;
	}

	public String removeBank(Bank b) {
		String removed = "bankRemoved";
		try {
			if (b != null) {
				Bank bb = em.find(Bank.class, b.getId());
				em.remove(bb);
			}
		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
		}
		return removed;
	}
}